#pragma once

#include <iostream>
#include <string>
#include <unordered_map>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

class user
{
public:
    user(int sockfd, std::string ip, uint16_t port) :_ip(ip), _port(port)
    {}
    ~user()
    {}

    std::string getip() const {return _ip;}
    uint16_t getport() const {return _port;}

 
private:
    std::string _ip;
    uint16_t _port;
};


class userManager
{
public:
    userManager()
    {}

    void addUser(int sockfd, const std::string& ip, uint16_t port)
    {
        std::string name = ip +  '-' + std::to_string(port);
        users.insert(std::make_pair(name, user(sockfd, ip, port)));
    }

    void delUser(const std::string& ip, uint16_t port)
    {   
        std::string name = ip + '-' + std::to_string(port);
        users.erase(name);
    }

    bool is_Online(const std::string& ip, uint16_t port) const
    {
        std::string name = ip + '-' + std::to_string(port);
        return users.find(name) == users.end()? false : true;
    }

    void broadcast(int sockfd, std::string message) const
    {
        for(auto &u : users)
        {
            struct sockaddr_in client;
            client.sin_family = AF_INET;
            client.sin_addr.s_addr = inet_addr(u.second.getip().c_str());
            client.sin_port = ntohs(u.second.getport());

            sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr*)&client, sizeof(client));
        }

    }

    ~userManager()
    {}
private:
    std::unordered_map<std::string, user> users;
};
